package com.kkb.kkbcommon.generic;

import com.kkb.kkbcommon.basic.BaseUtil;

import java.io.*;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * @Author: zml
 * @Description: 反射工具类
 * @Data Created in 2021-08-05 20:26
 * @Modified by:
 */
public class GenericUtil {
    /**
     * @Author: 朱明亮
     * @Description: 类型拷贝
     * @Data Created in 2021-07-12 17:54:19
     * @Modified by:
     */
    public static <T extends Serializable> T clone(T obj) {
        if (BaseUtil.haveNull(obj)){
            return null;
        }
        return deserialize(serialize(obj), (Class<T>) obj.getClass());
    }

    /**
     * @Author: zml
     * @Description: 将对象序列化为字节数组
     * @Data Created in 2021-07-13 11:28:54
     * @Modified by:
     */
    public static <T extends Serializable> byte[] serialize(T obj) {
        if (BaseUtil.haveNull(obj)){
            return null;
        }
        try (
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)
        ) {
            objectOutputStream.writeObject(obj);
            return byteArrayOutputStream.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * @Author: zml
     * @Description: 将字节数组反序列化为对象
     * @Data Created in 2021-05-31 12:02:57
     * @Modified by:
     *
     * @param bytes 字节数组
     * @return 反序列化后的对象
     */
    public static <T extends Serializable> T deserialize(byte[] bytes, Class<T> tClass){
        if (BaseUtil.haveEmpty(bytes, tClass)){
            return null;
        }
        try(ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
            ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        ){
            return (T) objectInputStream.readObject();
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * @Author: zml
     * @Description: 获取绑定的类的类型
     * @Data Created in 2021-07-30 14:09:23
     * @Modified by:
     *
     * @param <T> 当前class上绑定的第n个泛型
     * @param sClass 当前类
     */
    public static  <T extends Object> Class<T> getTClass(Class sClass, int index){
        // 用来返回表示当前Class 所表示的实体（类、接口、基本类型或 void）的直接超类的Type。
        // 如果这个直接超类是参数化类型的，则返回的Type对象必须明确反映在源代码中声明时使用的类型
        Type genericSuperclass = sClass.getGenericSuperclass();
        // 判断获取到的类型是否为参数化类型
        if (genericSuperclass instanceof ParameterizedType){
            // 如果是参数化类型则进行强转
            ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
            // 获取其中的所有类型
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            // 我们只有一个类型只需要获取第一个即可
            if (actualTypeArguments.length>=1){
                // 获取到第n个类型
                Type actualTypeArgument = actualTypeArguments[index];
                // 判断是否属于class类型
                if (actualTypeArgument instanceof Class){
                    // 强转为class类型
                    return (Class) actualTypeArgument;
                }
            }
        }
        return null;
    }
}
